package com.gwnet.rider.service.impl;

import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gwnet.common.core.exception.base.BaseException;
import com.gwnet.common.enums.IOTypeEnum;
import com.gwnet.common.enums.OwnerTypeEnum;
import com.gwnet.common.satoken.utils.LoginHelper;
import com.gwnet.common.util.Arith;
import com.gwnet.rider.domain.PlatformWalletLog;
import com.gwnet.rider.domain.RiderRegionRecord;
import com.gwnet.rider.domain.RiderUser;
import com.gwnet.rider.domain.RiderWallet;
import com.gwnet.rider.domain.bo.GrabOrderBO;
import com.gwnet.rider.domain.bo.OrderPageBO;
import com.gwnet.rider.enums.RiderStatusEnum;
import com.gwnet.rider.enums.WorkStatusEnums;
import com.gwnet.rider.mapper.PlatformWalletLogMapper;
import com.gwnet.rider.mapper.RiderUserMapper;
import com.gwnet.rider.mapper.RiderWalletMapper;
import com.gwnet.rider.service.GrabOrderService;
import com.gwnet.rider.service.RiderRegionRecordService;
import com.gwnet.shop.domain.OrderDelivery;
import com.gwnet.shop.domain.OrderInfo;
import com.gwnet.shop.enums.DevStatusEnum;
import com.gwnet.shop.enums.OrderStatusEnum;
import com.gwnet.shop.mapper.OrderDeliveryMapper;
import com.gwnet.shop.mapper.OrderInfoMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 接单记录 服务实现类
 * </p>
 *
 * @author WangLiang
 * @since 2024-07-31
 */
@Service
public class GrabOrderServiceImpl implements GrabOrderService {

    @Resource
    private OrderInfoMapper orderInfoMapper;

    @Resource
    private RiderUserMapper riderUserMapper;

    @Resource
    private OrderDeliveryMapper orderDeliveryMapper;

    @Resource
    private RiderRegionRecordService regionRecordService;

    @Resource
    private PlatformWalletLogMapper platformWalletLogMapper;

    @Resource
    private RiderWalletMapper riderWalletMapper;


    @Override
    public IPage<OrderInfo> orderPage(OrderPageBO pageBO) {
        RiderUser user = getUser();

        // 查询骑手负责的区域
        LambdaQueryWrapper<RiderRegionRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RiderRegionRecord::getRiderId,user.getRiderId());
        List<RiderRegionRecord> regionRecords = regionRecordService.list(queryWrapper);
        List<Long> schoolIds = regionRecords.stream().map(RiderRegionRecord::getSchoolId).collect(Collectors.toList());


        // 分页查询订单数据
        Page<OrderInfo> page = Page.of(pageBO.getCurrent(), pageBO.getSize());

        LambdaQueryWrapper<OrderInfo> orderWrapper = new LambdaQueryWrapper<>();
        // TODO 根据学校 + 订单的宿舍楼地址Id（一级地址即可） 去筛选订单信息; 这里先筛选学校ID，后续等地址确定后再加入楼号的过滤
        orderWrapper.in(OrderInfo::getSchoolId,schoolIds)
//                .eq(OrderInfo::getOrderStatus,OrderStatusEnum.WAIT_RECEIVE_ORDER.code())
        ;
        Page<OrderInfo> pageResult = orderInfoMapper.selectPage(page, orderWrapper);

        return pageResult;
    }



    @Transactional(rollbackFor = Exception.class)
    @Lock4j(keys = {"#grabOrderBO.getOrderId()"})
    @Override
    public OrderInfo grabOrder(GrabOrderBO grabOrderBO) {
        Long userId = LoginHelper.getLoginUser().getUserId();
        OrderInfo orderInfo = orderInfoMapper.selectById(grabOrderBO.getOrderId());
        OrderDelivery orderDelivery = orderDeliveryMapper.selectOrderDeliveryById(orderInfo.getDeliveryId());
        if(ObjectUtils.isNotEmpty(orderDelivery.getRiderId())){
            throw new BaseException("该订单已经被别人抢走了，请刷新后重试");
        }
        // 骑手ID
        orderDelivery.setRiderId(userId);
        // 配送状态 待到店
        orderDelivery.setDeliveryStatus(DevStatusEnum.WAIT_TO_STORE.code());
        // 来源：1.抢单 2.平台派单
        orderDelivery.setSource(1);
        orderDeliveryMapper.updateById(orderDelivery);

        // 修改主表状态
        orderInfo.setOrderStatus(OrderStatusEnum.WAIT_TO_STORE.code());
        orderInfoMapper.updateById(orderInfo);

        // 修改财务表状态，回填骑手抢单ID
        LambdaQueryWrapper<PlatformWalletLog> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(PlatformWalletLog::getOrderId,grabOrderBO.getOrderId())
                .eq(PlatformWalletLog::getOwnerType, OwnerTypeEnum.RIDER.code())
                .eq(PlatformWalletLog::getIoType, IOTypeEnum.IN.code());

        List<PlatformWalletLog> list = platformWalletLogMapper.selectList(queryWrapper);
        if(list.size() > 0){
            PlatformWalletLog log = list.get(0);
            log.setOwnerId(userId);
            platformWalletLogMapper.updateById(log);

            // 骑手冻结金额
            RiderWallet riderWallet = riderWalletMapper.selectById(userId);
            double newFreezeAmount = Arith.add(riderWallet.getFreezeAmount(), log.getChangeAmount());
            riderWallet.setFreezeAmount(newFreezeAmount);
            riderWalletMapper.updateById(riderWallet);

        }



        return orderInfo;
    }

    /**
     * 超时订单推送到MQ
     * @param minute 超时标准，多少分钟算超时
     * @return
     */
    @Override
    public List<OrderInfo> timeOutOrderPushToMQ(Integer minute) {
        // 不传时间默认超过15分钟没人接单就算超时订单
        if (ObjectUtils.isEmpty(minute)) {
            minute = 15;
        }

        // 定义一个 LocalDateTime 对象  当前时间
        LocalDateTime nowDate = LocalDateTime.now();

        // 分批查询数据，先查超时未接订单的总数量
        Integer total = orderInfoMapper.selectTimeOutCount(minute, nowDate);

        // 定义每页的大小 每次查询100条
        int pageSize = 100;
        // 计算总页数
        int totalPages = (total + pageSize - 1) / pageSize;
        // 用于存储所有超时订单
        List<OrderInfo> allTimeOutOrders = new ArrayList<>();

        // 分页查询数据列表，遍历进行推送
        for (int page = 1; page <= totalPages; page++) {
            // 计算偏移量
            int offset = (page - 1) * pageSize;
            List<OrderInfo> timeOutOrders = orderInfoMapper.selectTimeOutList(minute, nowDate, offset, pageSize);

            // 遍历订单并进行推送到消息队列
            for (OrderInfo order : timeOutOrders) {
                // 这里调用推送到 MQ 的方法
                pushToMQ(order);
            }

            // 将查询到的订单添加到总列表中
            allTimeOutOrders.addAll(timeOutOrders);
        }
        // 返回所有超时订单
        return allTimeOutOrders;
    }

    /**
     * 推送订单信息到MQ中
     * @param order
     */
    private void pushToMQ(OrderInfo order) {
        // 使用feign远程调用消息中心服务，将订单推送到指定交换机
        // mqService.send(order.getOrderId);
    }

    /**
     * 获取抢单的骑手信息
     * @return 骑手信息
     */
    private RiderUser getUser(){
        Long userId = LoginHelper.getLoginUser().getUserId();
        RiderUser user = riderUserMapper.selectById(userId);
        // 判断骑手是否是被禁用的 状态 1 正常 0 无效
        if(RiderStatusEnum.DISABLE.code().equals(user.getStatus())){
            throw new BaseException("您已经被禁用");
        }
        // 判断骑手是否在接单中 1.接单 0.停止接单
        if(WorkStatusEnums.STOP.code().equals(user.getWorkStatus())){
            throw new BaseException("您已经停止接单");
        }
        return user;
    }
}
